package com.wgz.flag.websocket;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wgz.flag.entity.ChatMessage;
import com.wgz.flag.entity.PrivateMessage;
import com.wgz.flag.entity.WebSocketMessage;
import com.wgz.flag.domain.dto.GroupMessageDTO;
import com.wgz.flag.enums.ContentType;
import com.wgz.flag.enums.MessageType;
import com.wgz.flag.service.PrivateMessageService;
import com.wgz.flag.service.GroupMessageService;
import com.wgz.flag.service.GroupMemberService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.alibaba.fastjson.JSON.*;

@Slf4j
@Component
@ServerEndpoint("/websocket/{userId}")
public class ChatWebSocketServer {
    private static ObjectMapper objectMapper;
    private static PrivateMessageService privateMessageService;
    private static GroupMessageService groupMessageService;
    private static GroupMemberService groupMemberService;

    @Autowired
    public void setObjectMapper(ObjectMapper mapper) {
        ChatWebSocketServer.objectMapper = mapper;
    }

    @Autowired
    public void setPrivateMessageService(PrivateMessageService service) {
        ChatWebSocketServer.privateMessageService = service;
    }

    @Autowired
    public void setGroupMessageService(GroupMessageService service) {
        ChatWebSocketServer.groupMessageService = service;
    }

    @Autowired
    public void setGroupMemberService(GroupMemberService service) {
        ChatWebSocketServer.groupMemberService = service;
    }

    @OnOpen
    public void onOpen(Session session, @PathParam("userId") Long userId) {
        log.info("New WebSocket connection established for user: {}", userId);
        WebSocketSessionManager.addSession(userId, session);
    }

    @OnClose
    public void onClose(@PathParam("userId") Long userId) {
        log.info("WebSocket connection closed for user: {}", userId);
        WebSocketSessionManager.removeSession(userId);
    }

    @OnMessage
    public void onMessage(String message, @PathParam("userId") Long userId) {
        try {
            ChatMessage chatMessage = parseObject(message, ChatMessage.class);
            // 使用路径参数中的 userId 作为发送者ID
            chatMessage.setSenderId(userId);
            log.info("Received message from user {}: {}", userId, message);
            log.info("Message type: {}", chatMessage.getMessageType());

            if (chatMessage.getMessageType() == MessageType.PRIVATE.getValue()) {
                log.info("Handling private message");
                handlePrivateMessage(chatMessage);
            } else if (chatMessage.getMessageType() == MessageType.GROUP.getValue()) {
                log.info("Handling group message");
                handleGroupMessage(chatMessage);
            }
        } catch (Exception e) {
            log.error("处理消息失败: {}", message, e);
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.error("WebSocket错误", error);
    }

    @Scheduled(fixedRate = 30000)
    public void sendHeartbeat() {
        for (Session session : WebSocketSessionManager.getAllSessions()) {
            try {
                session.getBasicRemote().sendText("heartbeat");
            } catch (IOException e) {
                log.error("发送心跳失败", e);
            }
        }
    }

    private void handlePrivateMessage(ChatMessage message) {
        // 获取接收者的session
        Session receiverSession = WebSocketSessionManager.getSession(message.getReceiverId());
//        if (receiverSession != null && receiverSession.isOpen()) {
//            sendMessage(receiverSession, message);
//        }

        // 转换为 PrivateMessage 并保存
        PrivateMessage privateMessage = new PrivateMessage();
        BeanUtils.copyProperties(message, privateMessage);
        if (message.getContentType() == 0) {
            privateMessage.setMessageType(1);
        } else if (message.getContentType() == 1) {
            privateMessage.setMessageType(2);
        } else if (message.getContentType() == 4) {
            privateMessage.setMessageType(3);
        }
        privateMessage.setStatus(1);
        log.info("privateMessage:{}", privateMessage);
        privateMessageService.sendMessage(privateMessage);
        log.info("Sending private message to receive: {}", message.getReceiverId());
        // 转发给接收者
        if (receiverSession != null && receiverSession.isOpen()) {
            sendMessage(receiverSession, message);
        }
    }

    private void handleGroupMessage(ChatMessage message) {
        List<Long> memberIds = groupMemberService.getGroupMemberIds(message.getGroupId());
        log.info("Broadcasting group message to members: {}", memberIds);

        // 构建群聊消息
        GroupMessageDTO groupMessageDTO = new GroupMessageDTO();
        BeanUtils.copyProperties(message, groupMessageDTO);
        groupMessageDTO.setStatus(1);

        // 先保存到数据库
        groupMessageService.sendMessage(message.getSenderId(), groupMessageDTO);

        // 转发给所有群成员（除了发送者）
        for (Long memberId : memberIds) {
            if (memberId.equals(message.getSenderId())) {
                continue;
            }
            Session memberSession = WebSocketSessionManager.getSession(memberId);
            if (memberSession != null && memberSession.isOpen()) {
                log.info("Sending group message to member: {}", memberId);
                // 创建一个新的消息对象，确保包含所有必要的信息
                ChatMessage forwardMessage = new ChatMessage();
                BeanUtils.copyProperties(message, forwardMessage);
                sendMessage(memberSession, forwardMessage);
            }
        }
    }

    private void sendMessage(Session session, ChatMessage message) {
        try {
            Map<String, Object> wsMessage = new HashMap<>();
            if (message.getMessageType() == MessageType.GROUP.getValue()) {
                wsMessage.put("messageType", MessageType.GROUP.getValue());
                wsMessage.put("content", message.getContent());
                wsMessage.put("senderId", message.getSenderId());
                wsMessage.put("groupId", message.getGroupId());
                wsMessage.put("contentType", message.getContentType());
                wsMessage.put("status", message.getStatus());
                wsMessage.put("createTime", message.getCreateTime());

                // 如果是文件消息，添加文件相关信息
                if (message.getContentType() == ContentType.FILE.getValue()) {
                    log.info("Processing Group file message: {}", message);
                    wsMessage.put("fileName", message.getFileName());
                    wsMessage.put("fileSize", message.getFileSize());
                }

                String messageText = JSON.toJSONString(wsMessage);
                log.info("Group - Sending WebSocket message: {}", messageText);
                session.getAsyncRemote().sendText(messageText);
                Long userId = WebSocketSessionManager.getUserIdBySession(session);
                log.info("Group - Successfully sent message to user {}", userId);
            }else if (message.getMessageType() == MessageType.PRIVATE.getValue()) {
                wsMessage.put("messageType", MessageType.PRIVATE.getValue());
                wsMessage.put("content", message.getContent());
                wsMessage.put("senderId", message.getSenderId());
                wsMessage.put("receiverId", message.getReceiverId());
                wsMessage.put("contentType", message.getContentType());
                wsMessage.put("status", message.getStatus());
                wsMessage.put("readStatus", message.getReadStatus());
                wsMessage.put("createTime", message.getCreateTime());

                // 如果是文件消息，添加文件相关信息
                if (message.getContentType() == ContentType.FILE.getValue()) {
                    log.info("Processing Private file message: {}", message);
                    wsMessage.put("fileName", message.getFileName());
                    wsMessage.put("fileSize", message.getFileSize());
                }

                String messageText = JSON.toJSONString(wsMessage);
                log.info("Private - Sending WebSocket message: {}", messageText);
                session.getAsyncRemote().sendText(messageText);
                Long userId = WebSocketSessionManager.getUserIdBySession(session);
                log.info("Private - Successfully sent message to user {}", userId);

            }
        } catch (Exception e) {
            log.error("发送消息失败", e);
        }
    }

    public void sendMessage(Long userId, String type, Object data) {
        Session session = WebSocketSessionManager.getSession(userId);
        if (session != null && session.isOpen()) {
            try {
                WebSocketMessage message = new WebSocketMessage();
                message.setType(type);
                message.setData(data);
                session.getBasicRemote().sendText(toJSONString(message));
            } catch (IOException e) {
                log.error("发送WebSocket消息失败", e);
            }
        }
    }
}